home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / LIBPNG / EXAMPLE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-14  |  17.8 KB  |  531 lines  |  [TEXT/CWIE]

  1. /* example.c - an example of using libpng */
  2.  
  3. /* this is an example of how to use libpng to read and write
  4.    png files.  The file libpng.txt is much more verbose then
  5.    this.  If you have not read it, do so first.  This was
  6.    designed to be a starting point of an implementation.
  7.    This is not officially part of libpng, and therefore
  8.    does not require a copyright notice.
  9.  
  10.    This file does not currently compile, because it is missing
  11.    certain parts, like allocating memory to hold an image.
  12.    You will have to supply these parts to get it to compile.
  13.    */
  14.  
  15. #include <png.h>
  16.  
  17. /* Check to see if a file is a png file using png_check_sig().
  18.  
  19.    If this call is successful, and you are going to keep the file
  20.    open, you should call png_set_sig_bytes_read(png_ptr, 8);
  21.    once you have created the png_ptr, so that libpng knows it
  22.    doesn't have to read the signature again.  Make sure you don't
  23.    call png_set_sig_bytes_read() with more than 8 bytes read or
  24.    give it an incorrect number of bytes read, or you will either
  25.    have read too many bytes (your fault), or you are telling libpng
  26.    to read the wrong number of magic bytes (also your fault). */
  27. int check_png(char *file_name, FILE **fp)
  28. {
  29.    char buf[8];
  30.    int ret;
  31.  
  32.    *fp = fopen(file_name, "rb");
  33.    if (!fp)
  34.       return 0;
  35.    ret = fread(buf, 1, 8, *fp);
  36.  
  37.    if (ret != 8)
  38.       return 0;
  39.  
  40.    /* Check the signature starting at byte 0, and check all 8 bytes */
  41.    ret = png_check_sig(buf, 0, 8);
  42.  
  43.    return (ret);
  44. }
  45.  
  46. /* read a png file.  You may want to return an error code if the read
  47.    fails (depending upon the failure).  There are two "prototypes" given
  48.    here - one where we are given the filename, and we need to open the
  49.    file, and the other where we are given an open file (possibly with
  50.    some or all of the magic bytes read - see above) and an opened file
  51.    for reading. */
  52. ------- prototype 1 ----------
  53. void read_png(char *file_name)  /* We need to open the file */
  54. {
  55.    png_structp png_ptr;
  56.    png_infop info_ptr;
  57.    FILE *fp;
  58.  
  59.    if ((fp = fopen(file_name, "rb")) == NULL)
  60.       return;
  61. ------- prototype 2 ----------
  62. void read_png(FILE *fp, unsigned int sig_read)  /* file is already open */
  63. {
  64.    png_structp png_ptr;
  65.    png_infop info_ptr;
  66. ------- only use one! --------
  67.  
  68.    /* Create and initialize the png_struct with the desired error handler
  69.       functions.  If you want to use the default stderr and longjump method,
  70.       you can supply NULL for the last three parameters.  We also check that
  71.       the header file is compatible with the library version.  */
  72.    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
  73.       (void *)user_error_ptr, user_error_fn, user_warning_fn);
  74.  
  75.    if (!png_ptr)
  76.    {
  77.       fclose(fp);
  78.       return;
  79.    }
  80.  
  81.    info_ptr = png_create_info_struct();
  82.    if (!info_ptr)
  83.    {
  84.       fclose(fp);
  85.       png_destroy_read_struct(&png_ptr,  (png_infopp)NULL, (png_infopp)NULL);
  86.       return;
  87.    }
  88.  
  89.    /* set error handling if you are using the setjmp/longjmp method */
  90.    if (setjmp(png_ptr->jmpbuf))
  91.    {
  92.       /* Free all of the memory associated with the png_ptr and info_ptr */
  93.       png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
  94.       fclose(fp);
  95.       /* If we get here, we had a problem reading the file */
  96.       return;
  97.    }
  98.  
  99.    /* set up the input control if you are using standard C streams */
  100.    png_init_io(png_ptr, fp);
  101.  
  102.    /* if you are using replacement read functions, instead of calling
  103.       png_init_io() here you would call */
  104.    png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
  105.    /* where user_io_ptr is a structure you want available to the callbacks */
  106.  
  107.    /* if we have already read some of the signature from the beginning call */
  108.    png_set_sig_bytes_read(png_ptr, sig_read);
  109.  
  110.    /* The call to png_read_info() gives us all of the information
  111.       from the PNG file before the first IDAT (image data chunk). */
  112.    png_read_info(png_ptr, info_ptr);
  113.  
  114.    /* set up the transformations you want.  Note that these are
  115.       all optional.  Only call them if you want them */
  116.  
  117.    /* expand paletted colors into true RGB triplets */
  118.    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  119.       png_set_expand(png_ptr);
  120.  
  121.    /* expand grayscale images to the full 8 bits */
  122.    if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY && info_ptr->bit_depth < 8)
  123.       png_set_expand(png_ptr);
  124.  
  125.    /* expand paletted or RGB images with transparency to full alpha channels
  126.     * so the data will be available as RGBA quartets */
  127.    if (info_ptr->valid & PNG_INFO_tRNS)
  128.       png_set_expand(png_ptr);
  129.  
  130.    /* Set the background color to draw transparent and alpha
  131.       images over.  It is possible to set the red, green, and blue
  132.       components directly for paletted images. */
  133.  
  134.    png_color_16 my_background;
  135.  
  136.    if (info_ptr->valid & PNG_INFO_bKGD)
  137.       png_set_background(png_ptr, &(info_ptr->background),
  138.                          PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
  139.    else
  140.       png_set_background(png_ptr, &my_background,
  141.                          PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
  142.  
  143.    /* tell libpng to handle the gamma conversion for you.  We only
  144.       need the second call if the screen_gamma isn't the usual 2.2
  145.       or if it is controllable by the user.  It may also be a good
  146.       idea to allow the user to set the file gamma if it is unknown. */
  147.    if (info_ptr->valid & PNG_INFO_gAMA)
  148.       png_set_gamma(png_ptr, screen_gamma, info_ptr->gamma);
  149.    else
  150.       png_set_gamma(png_ptr, screen_gamma, 0.45);
  151.  
  152.    /* tell libpng to strip 16 bit/color files down to 8 bits/color */
  153.    if (info_ptr->bit_depth == 16)
  154.       png_set_strip_16(png_ptr);
  155.  
  156.    /* dither rgb files down to 8 bit palette & reduce palettes
  157.       to the number of colors available on your screen */
  158.    if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
  159.    {
  160.       if (info_ptr->valid & PNG_INFO_PLTE)
  161.          png_set_dither(png_ptr, info_ptr->palette, info_ptr->num_palette,
  162.                         max_screen_colors, info_ptr->histogram);
  163.       else
  164.       {
  165.          png_color std_color_cube[MAX_SCREEN_COLORS] =
  166.             {/* ... colors ... */};
  167.  
  168.          png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
  169.             MAX_SCREEN_COLORS, NULL);
  170.       }
  171.    }
  172.  
  173.    /* invert monocrome files to have 0 as white and 1 as black */
  174.    if (info_ptr->bit_depth == 1 && info_ptr->color_type == PNG_COLOR_GRAY)
  175.       png_set_invert(png_ptr);
  176.  
  177.    /* shift the pixels down to their true bit depth */
  178.    if (info_ptr->valid & PNG_INFO_sBIT &&
  179.       info_ptr->bit_depth > info_ptr->sig_bit)
  180.       png_set_shift(png_ptr, &(info_ptr->sig_bit));
  181.  
  182.    /* pack multiple pixels with bit depths of 1, 2, and 4 into bytes
  183.       (useful only for paletted and grayscale images) */
  184.    if (info_ptr->bit_depth < 8)
  185.       png_set_packing(png_ptr);
  186.  
  187.    /* flip the rgb pixels to bgr */
  188.    if (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
  189.       info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  190.       png_set_bgr(png_ptr);
  191.  
  192.    /* swap bytes of 16 bit files to least significant bit first */
  193.    if (info_ptr->bit_depth == 16)
  194.       png_set_swap(png_ptr);
  195.  
  196.    /* add a filler byte to RGB files (before or after each RGB triplet) */
  197.    if (info_ptr->bit_depth == 8 && info_ptr->color_type == PNG_COLOR_TYPE_RGB)
  198.       png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
  199.  
  200.    /* turn on interlace handling if you are not using png_read_image() */
  201.    number_passes = png_set_interlace_handling(png_ptr);
  202.  
  203.    /* optional call to gamma correct and add the background to the palette
  204.       and update info structure. */
  205.    png_read_update_info(png_ptr, info_ptr);
  206.  
  207.    /* allocate the memory to hold the image using the fields
  208.       of png_info. */
  209.  
  210.    /* the easiest way to read the image */
  211.    png_bytep row_pointers[height];
  212.  
  213.    for (row = 0; row < height; row++)
  214.    {
  215.      row_pointers[row] = malloc(info_ptr->rowbytes);
  216.    }
  217.  
  218.    png_read_image(png_ptr, row_pointers);
  219.  
  220.    /* the other way to read images - deal with interlacing */
  221.  
  222.    for (pass = 0; pass < number_passes; pass++)
  223.    {
  224.       /* Read the image using the "sparkle" effect. */
  225.       png_read_rows(png_ptr, row_pointers, NULL, number_of_rows);
  226.  
  227.       /* If you are only reading on row at a time, this works */
  228.       for (y = 0; y < height; y++)
  229.       {
  230.          png_bytep row_pointers = row[y];
  231.          png_read_rows(png_ptr, &row_pointers, NULL, 1);
  232.       }
  233.  
  234.       /* to get the rectangle effect, use the third parameter */
  235.       png_read_rows(png_ptr, NULL, row_pointers, number_of_rows);
  236.  
  237.       /* if you want to display the image after every pass, do
  238.          so here */
  239.    }
  240.  
  241.    /* read the rest of the file, getting any additional chunks in info_ptr */
  242.    png_read_end(png_ptr, info_ptr);
  243.  
  244.    /* clean up after the read, and free any memory allocated */
  245.    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
  246.  
  247.    /* close the file */
  248.    fclose(fp);
  249.  
  250.    /* that's it */
  251.    return;
  252. }
  253.  
  254. /* progressively read a file */
  255.  
  256. int
  257. initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
  258. {
  259.    /* Create and initialize the png_struct with the desired error handler
  260.       functions.  If you want to use the default stderr and longjump method,
  261.       you can supply NULL for the last three parameters.  We also check that
  262.       the library version is compatible in case we are using dynamically
  263.       linked libraries.
  264.     */
  265.    *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
  266.        (void *)user_error_ptr, user_error_fn, user_warning_fn);
  267.  
  268.    if (! *png_ptr)
  269.    {
  270.       *info_ptr = NULL;
  271.       return ERROR;
  272.    }
  273.  
  274.    *info_ptr = png_create_info_struct(png_ptr);
  275.  
  276.    if (! *info_ptr)
  277.    {
  278.       png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
  279.       return ERROR;
  280.    }
  281.  
  282.    if (setjmp((*png_ptr)->jmpbuf))
  283.    {
  284.       png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
  285.       return ERROR;
  286.    }
  287.  
  288.    /* this one's new.  You will need to provide all three
  289.       function callbacks, even if you aren't using them all.
  290.       These functions shouldn't be dependent on global or
  291.       static variables if you are decoding several images
  292.       simultaneously.  You should store stream specific data
  293.       in a separate struct, given as the second parameter,
  294.       and retrieve the pointer from inside the callbacks using
  295.       the function png_get_progressive_ptr(png_ptr). */
  296.    png_set_progressive_read_fn(*png_ptr, (void *)stream_data,
  297.       info_callback, row_callback, end_callback);
  298.  
  299.    return OK;
  300. }
  301.  
  302. int
  303. process_data(png_structp *png_ptr, png_infop *info_ptr,
  304.    png_bytep buffer, png_uint_32 length)
  305. {
  306.    if (setjmp((*png_ptr)->jmpbuf))
  307.    {
  308.       /* Free the png_ptr and info_ptr memory on error */
  309.       png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
  310.       return ERROR;
  311.    }
  312.  
  313.    /* this one's new also.  Simply give it chunks of data as
  314.       they arrive from the data stream (in order, of course).
  315.       On Segmented machines, don't give it any more than 64K.
  316.       The library seems to run fine with sizes of 4K, although
  317.       you can give it much less if necessary (I assume you can
  318.       give it chunks of 1 byte, but I haven't tried with less
  319.       than 256 bytes yet).  When this function returns, you may
  320.       want to display any rows that were generated in the row
  321.       callback, if you aren't already displaying them there. */
  322.    png_process_data(*png_ptr, *info_ptr, buffer, length);
  323.    return OK;
  324. }
  325.  
  326. info_callback(png_structp png_ptr, png_infop info)
  327. {
  328. /* do any setup here, including setting any of the transformations
  329.    mentioned in the Reading PNG files section.  For now, you _must_
  330.    call either png_start_read_image() or png_read_update_info()
  331.    after all the transformations are set (even if you don't set
  332.    any).  You may start getting rows before png_process_data()
  333.    returns, so this is your last chance to prepare for that. */
  334. }
  335.  
  336. row_callback(png_structp png_ptr, png_bytep new_row,
  337.    png_uint_32 row_num, int pass)
  338. {
  339. /* this function is called for every row in the image.  If the
  340.    image is interlacing, and you turned on the interlace handler,
  341.    this function will be called for every row in every pass.
  342.    Some of these rows will not be changed from the previous pass.
  343.    When the row is not changed, the new_row variable will be NULL.
  344.    The rows and passes are called in order, so you don't really
  345.    need the row_num and pass, but I'm supplying them because it
  346.    may make your life easier.
  347.  
  348.    For the non-NULL rows of interlaced images, you must call
  349.    png_progressive_combine_row() passing in the row and the
  350.    old row.  You can call this function for NULL rows (it will
  351.    just return) and for non-interlaced images (it just does the
  352.    memcpy for you) if it will make the code easier.  Thus, you
  353.    can just do this for all cases: */
  354.  
  355.    png_progressive_combine_row(png_ptr, old_row, new_row);
  356.  
  357. /* where old_row is what was displayed for previous rows.  Note
  358.    that the first pass (pass == 0 really) will completely cover
  359.    the old row, so the rows do not have to be initialized.  After
  360.    the first pass (and only for interlaced images), you will have
  361.    to pass the current row, and the function will combine the
  362.    old row and the new row. */
  363. }
  364.  
  365. end_callback(png_structp png_ptr, png_infop info)
  366. {
  367. /* this function is called when the whole image has been read,
  368.    including any chunks after the image (up to and including
  369.    the IEND).  You will usually have the same info chunk as you
  370.    had in the header, although some data may have been added
  371.    to the comments and time fields.
  372.  
  373.    Most people won't do much here, perhaps setting a flag that
  374.    marks the image as finished. */
  375. }
  376.  
  377. /* write a png file */
  378. void write_png(char *file_name, ... other image information ...)
  379. {
  380.    FILE *fp;
  381.    png_structp png_ptr;
  382.    png_infop info_ptr;
  383.  
  384.    /* open the file */
  385.    fp = fopen(file_name, "wb");
  386.    if (!fp)
  387.       return;
  388.  
  389.    /* Create and initialize the png_struct with the desired error handler
  390.       functions.  If you want to use the default stderr and longjump method,
  391.       you can supply NULL for the last three parameters.  We also check that
  392.       the library version is compatible in case we are using dynamically
  393.       linked libraries.
  394.     */
  395.    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
  396.       (void *)user_error_ptr, user_error_fn, user_warning_fn);
  397.  
  398.    if (!png_ptr)
  399.    {
  400.       fclose(fp);
  401.       return;
  402.    }
  403.  
  404.    info_ptr = png_create_info_struct(png_ptr);
  405.    if (!info_ptr)
  406.    {
  407.       fclose(fp);
  408.       png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
  409.       return;
  410.    }
  411.  
  412.    /* set error handling */
  413.    if (setjmp(png_ptr->jmpbuf))
  414.    {
  415.       /* If we get here, we had a problem reading the file */
  416.       fclose(fp);
  417.       png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
  418.       return;
  419.    }
  420.  
  421.    /* set up the output control if you are using standard C streams */
  422.    png_init_io(png_ptr, fp);
  423.  
  424.    /* set the file information here */
  425.    info_ptr->width = ;
  426.    info_ptr->height = ;
  427.    etc.
  428.  
  429.    /* set the palette if there is one */
  430.    info_ptr->valid |= PNG_INFO_PLTE;
  431.    info_ptr->palette = malloc(256 * sizeof (png_color));
  432.    info_ptr->num_palette = 256;
  433.    ... set palette colors ...
  434.  
  435.    /* optional significant bit chunk */
  436.    info_ptr->valid |= PNG_INFO_sBIT;
  437.    /* if we are dealing with a grayscale image then */
  438.    info_ptr->sig_bit.gray = true_bit_depth;
  439.    /* otherwise, if we are dealing with a color image then */
  440.    info_ptr->sig_bit.red = true_red_bit_depth;
  441.    info_ptr->sig_bit.green = true_green_bit_depth;
  442.    info_ptr->sig_bit.blue = true_blue_bit_depth;
  443.    /* if the image has an alpha channel then */
  444.    info_ptr->sig_bit.alpha = true_alpha_bit_depth;
  445.   
  446.    /* optional gamma chunk is strongly suggested if you have any guess
  447.       as to the correct gamma of the image */
  448.    info_ptr->valid |= PNG_INFO_gAMA;
  449.    info_ptr->gamma = gamma;
  450.  
  451.    /* other optional chunks like cHRM, bKGD, tRNS, tEXt, tIME, oFFs, pHYs, */
  452.  
  453.    /* write the file header information */
  454.    png_write_info(png_ptr, info_ptr);
  455.  
  456.    /* set up the transformations you want.  Note that these are
  457.       all optional.  Only call them if you want them */
  458.  
  459.    /* invert monocrome pixels */
  460.    png_set_invert(png_ptr);
  461.  
  462.    /* shift the pixels up to a legal bit depth and fill in
  463.       as appropriate to correctly scale the image */
  464.    png_set_shift(png_ptr, &(info_ptr->sig_bit));
  465.  
  466.    /* pack pixels into bytes */
  467.    png_set_packing(png_ptr);
  468.  
  469.    /* flip bgr pixels to rgb */
  470.    png_set_bgr(png_ptr);
  471.  
  472.    /* swap bytes of 16 bit files to most significant bit first */
  473.    png_set_swap(png_ptr);
  474.  
  475.    /* get rid of filler bytes, pack rgb into 3 bytes.  The
  476.       filler number is not used. */
  477.    png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
  478.  
  479.    /* turn on interlace handling if you are not using png_write_image() */
  480.    if (interlacing)
  481.       number_passes = png_set_interlace_handling(png_ptr);
  482.    else
  483.       number_passes = 1;
  484.  
  485.    /* the easiest way to write the image (you may choose to allocate the
  486.       memory differently, however) */
  487.    png_byte row_pointers[height][width];
  488.  
  489.    png_write_image(png_ptr, row_pointers);
  490.  
  491.    /* the other way to write the image - deal with interlacing */
  492.  
  493.    for (pass = 0; pass < number_passes; pass++)
  494.    {
  495.       /* Write a few rows at a time. */
  496.       png_write_rows(png_ptr, row_pointers, number_of_rows);
  497.  
  498.       /* If you are only writing one row at a time, this works */
  499.       for (y = 0; y < height; y++)
  500.       {
  501.          png_bytep row_pointers = row[y];
  502.          png_write_rows(png_ptr, &row_pointers, 1);
  503.       }
  504.    }
  505.  
  506.    /* You can write optional chunks like tEXt, tIME at the end as well.
  507.     * Note that if you wrote tEXt or zTXt chunks before the image, and
  508.     * you aren't writing out more at the end, you have to set
  509.     * info_ptr->num_text = 0 or they will be written out again.
  510.     */
  511.  
  512.    /* write the rest of the file */
  513.    png_write_end(png_ptr, info_ptr);
  514.  
  515.    /* if you malloced the palette, free it here */
  516.    if (info_ptr->palette)
  517.       free(info_ptr->palette);
  518.  
  519.    /* if you allocated any text comments, free them here */
  520.  
  521.    /* clean up after the write, and free any memory allocated */
  522.    png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
  523.  
  524.    /* close the file */
  525.    fclose(fp);
  526.  
  527.    /* that's it */
  528.    return;
  529. }
  530.  
  531.